package com.liveinstars.gateway.business.service.impl;

import com.liveinstars.gateway.business.service.DynamicRouteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * @author: ting
 * @date: 2019-07-15
 */
@Service("dynamicRouteService")
public class DynamicRouteServiceImpl implements DynamicRouteService, ApplicationEventPublisherAware {

    private final static Logger logger = LoggerFactory.getLogger(DynamicRouteServiceImpl.class);

    @Autowired
    private InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository;

    private ApplicationEventPublisher publisher;

    @Override
    public boolean update(RouteDefinition routeDefinition) {
        try {
            inMemoryRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId()));
        } catch (Exception e) {
            logger.error("动态更新路由时删除路由信息异常", e);
        }
        try {
            inMemoryRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return true;
        } catch (Exception e) {
            logger.error("动态更新路由时保存路由信息异常", e);
        }
        return false;
    }

    @Override
    public boolean add(RouteDefinition routeDefinition) {
        try {
            this.inMemoryRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
        } catch (Exception e) {
            logger.error("");
            return false;
        }
        return true;
    }

    @Override
    public boolean deleteById(String id) {
        try {
            this.inMemoryRouteDefinitionRepository.delete(Mono.just(id)).then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build()))).subscribe();
        } catch (Exception e) {
            logger.error("");
            return false;
        }
        return true;
    }

    @Override
    public boolean updateAll(List<RouteDefinition> list) {
        try {
            Flux<RouteDefinition> routeDefinitions = inMemoryRouteDefinitionRepository.getRouteDefinitions();
            routeDefinitions.toStream().forEach(routeDefinition -> {
                inMemoryRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId())).subscribe();
            });
        } catch (Exception e) {
            logger.error("动态更新路由时删除路由信息异常", e);
        }
        try {
            list.stream().forEach(routeDefinition -> {
                inMemoryRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
            });
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return true;
        } catch (Exception e) {
            logger.error("动态更新路由时保存路由信息异常", e);
        }
        return false;
    }

    @Override
    public Flux<RouteDefinition> getRouters(){
        Flux<RouteDefinition> routeDefinitions = inMemoryRouteDefinitionRepository.getRouteDefinitions();
        return routeDefinitions;
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

}
